package net.goutalk.glcs.module.erpModel.caseErpUnit.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import net.goutalk.glcs.common.annotation.GlcsLog;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.YesOrNoEnum;
import net.goutalk.glcs.common.model.result.R;
import net.goutalk.glcs.common.page.ConventPage;
import net.goutalk.glcs.common.page.PageOutput;
import net.goutalk.glcs.common.utils.VoToColumnUtil;
import net.goutalk.glcs.module.erpModel.caseErpUnit.entity.CaseErpUnit;
import net.goutalk.glcs.module.erpModel.caseErpUnit.entity.CaseErpUnitConvertDetail;
import net.goutalk.glcs.module.erpModel.caseErpUnit.entity.CaseErpUnitType;
import net.goutalk.glcs.module.erpModel.caseErpUnit.service.ICaseErpUnitConvertDetailService;
import net.goutalk.glcs.module.erpModel.caseErpUnit.service.ICaseErpUnitService;
import net.goutalk.glcs.module.erpModel.caseErpUnit.service.ICaseErpUnitTypeService;
import net.goutalk.glcs.module.erpModel.caseErpUnit.vo.CaseErpUnitExportVo;
import net.goutalk.glcs.module.erpModel.caseErpUnit.vo.CaseErpUnitVo;
import net.goutalk.glcs.module.organization.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import net.goutalk.glcs.module.erpModel.caseErpUnit.dto.AddCaseErpUnitDto;
import net.goutalk.glcs.module.erpModel.caseErpUnit.dto.CaseErpUnitDto;
import net.goutalk.glcs.module.erpModel.caseErpUnit.dto.ImportCaseErpUnitDto;
import net.goutalk.glcs.module.erpModel.caseErpUnit.dto.UpdateCaseErpUnitDto;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping(GlobalConstant.CASE_ERP_UNIT +"/caseErpUnit")
@Api(value = GlobalConstant.CASE_ERP_UNIT +"/caseErpUnit", tags = "单位列表")
@AllArgsConstructor
public class CaseErpUnitController {

    private ICaseErpUnitService caseErpUnitService;

    private ICaseErpUnitConvertDetailService caseErpUnitConvertDetailService;

    private ICaseErpUnitTypeService caseErpUnitTypeService;

    @GetMapping(value = "/list")
    @ApiOperation("单位列表")
    public R list() {
        List<CaseErpUnit> list = caseErpUnitService.list();
        return R.ok(list);
    }

    @GetMapping(value = "/page")
    @ApiOperation("单位列表分页")
    public R page(CaseErpUnitDto dto) {
        IPage<CaseErpUnitVo> page = caseErpUnitService.selectJoinListPage(ConventPage.getPage(dto), CaseErpUnitVo.class,
                MPJWrappers.<CaseErpUnit>lambdaJoin()
                        .distinct()
                        .orderByDesc(CaseErpUnit::getUnitTypeId)
                        .like(StrUtil.isNotBlank(dto.getName()), CaseErpUnit::getName, dto.getName())
                        .eq(ObjectUtil.isNotEmpty(dto.getIsStandard()), CaseErpUnit::getIsStandard, dto.getIsStandard())
                        .selectAs(User::getName, CaseErpUnitVo::getCreateUserName)
                        .selectAs(CaseErpUnitType::getName, CaseErpUnitVo::getUnitTypeName)
                        .select(CaseErpUnit::getId)
                        .select(CaseErpUnit.class, x -> VoToColumnUtil.fieldsToColumns(CaseErpUnitVo.class).contains(x.getProperty()))
                        .leftJoin(CaseErpUnitType.class, CaseErpUnitType::getId, CaseErpUnit::getUnitTypeId)
                        .leftJoin(User.class, User::getId, CaseErpUnit::getCreateUserId));

        PageOutput<CaseErpUnitVo> pageOutput = ConventPage.getPageOutput(page);
        return R.ok(pageOutput);
    }

    @PostMapping
    @ApiOperation(value = "新增单位")
    public R add(@Valid @RequestBody AddCaseErpUnitDto dto) {
        long count = caseErpUnitService.count(Wrappers.<CaseErpUnit>query().lambda().eq(CaseErpUnit::getName, dto.getName()));
        if (count > 0) {
            return R.error("此单位已经存在！");
        }
        if (dto.getIsStandard() == YesOrNoEnum.YES.getCode()) {
            //查询到当前单位类型的所有单位
            caseErpUnitService.update(Wrappers.<CaseErpUnit>lambdaUpdate()
                    .eq(CaseErpUnit::getUnitTypeId, dto.getUnitTypeId())
                    .set(CaseErpUnit::getIsStandard, YesOrNoEnum.NO.getCode()));
        }
        CaseErpUnit caseErpUnit = BeanUtil.toBean(dto, CaseErpUnit.class);
        caseErpUnitService.save(caseErpUnit);
        return R.ok(true);
    }

    @PutMapping
    @ApiOperation(value = "修改单位")
    public R update(@Valid @RequestBody UpdateCaseErpUnitDto dto) {
        if (dto.getIsStandard() == YesOrNoEnum.YES.getCode()) {
            //查询到当前单位类型的所有单位
            caseErpUnitService.update(Wrappers.<CaseErpUnit>lambdaUpdate()
                    .eq(CaseErpUnit::getUnitTypeId, dto.getUnitTypeId())
                    .set(CaseErpUnit::getIsStandard, YesOrNoEnum.NO.getCode()));
        }
        CaseErpUnit caseErpUnit = BeanUtil.toBean(dto, CaseErpUnit.class);
        caseErpUnitService.updateById(caseErpUnit);
        return R.ok(true);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "根据id查询单位信息")
    public R info(@RequestParam Long id) {
        CaseErpUnit caseErpUnit = caseErpUnitService.getById(id);
        if (caseErpUnit == null) {
            R.error("找不到此单位！");
        }
        return R.ok(BeanUtil.toBean(caseErpUnit, CaseErpUnit.class));
    }


    @DeleteMapping
    @ApiOperation(value = "删除")
    @GlcsLog(value = "删除单位")
    public R delete(@Valid @RequestBody List<Long> ids) {
        List<CaseErpUnitConvertDetail> list = caseErpUnitConvertDetailService.list();
        List<CaseErpUnitConvertDetail> collect = list.stream().filter(x -> ids.contains(x.getBaseUnitId()) || ids.contains(x.getShiftUnitId())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(collect)){
            R.error("已进行单位换算配置的单位不能删除");
        }
        caseErpUnitService.removeBatchByIds(ids);
        return R.ok(true);
    }

    @PostMapping(value = "/export")
    @ApiOperation(value = "导出")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> export(@RequestBody List<Long> ids) {
        List<CaseErpUnitExportVo> caseErpUnitExportVoList = caseErpUnitService.selectJoinList(CaseErpUnitExportVo.class,
                MPJWrappers.<CaseErpUnit>lambdaJoin()
                        .distinct()
                        .in(CaseErpUnit::getId, ids)
                        .selectAs(User::getName, CaseErpUnitExportVo::getCreateUserName)
                        .selectAs(CaseErpUnitType::getName, CaseErpUnitExportVo::getUnitTypeName)
                        .select(CaseErpUnit::getId)
                        .select(CaseErpUnit.class, x -> VoToColumnUtil.fieldsToColumns(CaseErpUnitExportVo.class).contains(x.getProperty()))
                        .leftJoin(CaseErpUnitType.class, CaseErpUnitType::getId, CaseErpUnit::getUnitTypeId)
                        .leftJoin(User.class, User::getId, CaseErpUnit::getCreateUserId));
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CaseErpUnitExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(caseErpUnitExportVoList);
        return R.fileStream(bot.toByteArray(), "单位列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping("/import")
    @ApiOperation(value = "导入")
    public R importData(@RequestParam MultipartFile file) throws IOException {
        List<ImportCaseErpUnitDto> savedDataList = EasyExcel.read(file.getInputStream()).head(ImportCaseErpUnitDto.class).sheet().doReadSync();
        List<AddCaseErpUnitDto> addCaseErpUnitDtoList = new ArrayList<>();
        List<CaseErpUnitType> caseErpUnitTypeList = caseErpUnitTypeService.list();
        if (CollectionUtil.isNotEmpty(savedDataList)){
            for (ImportCaseErpUnitDto importCaseErpUnitDto : savedDataList) {
                AddCaseErpUnitDto addCaseErpUnitDto = BeanUtil.toBean(importCaseErpUnitDto, AddCaseErpUnitDto.class);
                CaseErpUnitType caseErpUnitType = caseErpUnitTypeList.stream().filter(x -> x.getName().equals(importCaseErpUnitDto.getUnitTypeName())).findFirst().orElse(new CaseErpUnitType());
                addCaseErpUnitDto.setIsStandard(YesOrNoEnum.NO.getCode());
                if (ObjectUtil.isNotEmpty(caseErpUnitType.getId())){
                    addCaseErpUnitDto.setUnitTypeId(caseErpUnitType.getId());
                    addCaseErpUnitDtoList.add(addCaseErpUnitDto);
                }else {
                    R.error("单位类型填写有误");
                }
            }
        }
        caseErpUnitService.saveBatch(BeanUtil.copyToList(addCaseErpUnitDtoList, CaseErpUnit.class));
        return R.ok(true);
    }

    @GetMapping("/export")
    @ApiOperation(value = "下载模板")
    @SneakyThrows
    public ResponseEntity<byte[]> export() {
        List<ImportCaseErpUnitDto> importCaseErpUnitDtos = new ArrayList<>();
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, ImportCaseErpUnitDto.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(BeanUtil.copyToList(importCaseErpUnitDtos, ImportCaseErpUnitDto.class));
        return R.fileStream(bot.toByteArray(), "单位列表模板" + ExcelTypeEnum.XLSX.getValue());
    }


    @GetMapping("/unit-list-by-unit-type")
    @ApiOperation(value = "根据单位类型id获取单位信息")
    public R getUnitByUnitTypeId(@RequestParam Long unitTypeId) {
        List<CaseErpUnit> caseErpUnitList = caseErpUnitService.selectJoinList(CaseErpUnit.class, MPJWrappers.<CaseErpUnit>lambdaJoin()
                .distinct()
                .eq(ObjectUtil.isNotEmpty(unitTypeId), CaseErpUnit::getUnitTypeId, unitTypeId)
                .eq(CaseErpUnit::getState, YesOrNoEnum.YES.getCode()));
        return R.ok(caseErpUnitList);
    }
}
